﻿' Copyright © Microsoft Corporation.  All Rights Reserved.
' This code released under the terms of the 
' Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
' <copyright file="PlaylistCollection.vb" company="Microsoft">
'     Copyright © Microsoft Corporation. All rights reserved.
' </copyright>
' <summary>Implements the PlaylistCollection class</summary>
' <author>Microsoft Expression Encoder Team</author>

Imports Microsoft.VisualBasic
Imports System
Imports System.ComponentModel
Imports System.Collections.Generic
Imports System.Diagnostics
Imports System.Windows
Imports System.Windows.Browser
Imports System.Windows.Media
Imports System.Threading
Imports System.Xml
Imports System.IO.IsolatedStorage
Imports System.IO
Imports System.Globalization
Imports System.Text

Namespace ExpressionMediaPlayer
	''' <summary>
	''' exception for invalid playlist
	''' </summary>
	Public Class InvalidPlaylistException
		Inherits Exception
		Public Sub New()
			MyBase.New(Resources.errorInvalidPlaylist)
		End Sub
		Public Sub New(ByVal message As String)
			MyBase.New(message)
		End Sub
		Public Sub New(ByVal nodeFound As String, ByVal nodeExpected As String)
			MyBase.New(String.Format(CultureInfo.CurrentUICulture, Resources.errorInvalidPlaylistNode, nodeFound, nodeExpected))
		End Sub
	End Class

	<ScriptableType> _
	Partial Public Class Playlist
		Inherits DependencyObject
		#Region "PlaylistCore"
		''' <summary>
		''' playlist options
		''' </summary>
		Private m_autoLoad As Boolean
		Private m_autoPlay As Boolean
		Private m_displayTimeCode As Boolean
		Private m_enableCachedComposition As Boolean
		Private m_enableCaptions As Boolean
		Private m_enableOffline As Boolean
		Private m_enablePopOut As Boolean
		Private m_startMuted As Boolean
		Private m_stretchMode As Stretch
		Private m_background As Color
		''' <summary>
		''' list of playlist items
		''' </summary>        
		Private _Items As New PlaylistCollection()
		''' <summary>
		''' playlist changed event
		''' </summary>
		<ScriptableMember> _
		Public Event PlaylistChanged As RoutedEventHandler
		''' <summary>
		''' should playlist cue up 
		''' </summary>
		<Description("Automatically cue video when page is loaded"), DefaultValue(True)> _
		Public Property AutoLoad() As Boolean
			Get
				Return m_autoLoad
			End Get
			Set(ByVal value As Boolean)
				m_autoLoad = value
				RaiseEvent PlaylistChanged(Me, Nothing)
			End Set
		End Property
		''' <summary>
		''' should playlist auto start?
		''' </summary>
		<Description("Automatically start video when cued"), DefaultValue(True)> _
		Public Property AutoPlay() As Boolean
			Get
				Return m_autoPlay
			End Get
			Set(ByVal value As Boolean)
				m_autoPlay = value
				RaiseEvent PlaylistChanged(Me, Nothing)
			End Set
		End Property
		''' <summary>
		''' display timecodes
		''' </summary>
		<Description("Display Timecode")> _
		Public Property DisplayTimeCode() As Boolean
			Get
				Return m_displayTimeCode
			End Get
			Set(ByVal value As Boolean)
				m_displayTimeCode = value
				RaiseEvent PlaylistChanged(Me, Nothing)
			End Set
		End Property
		''' <summary>
		''' cached composition enabled
		''' </summary>
		<Description("Enable Cached Composition"), DefaultValue(True)> _
		Public Property EnableCachedComposition() As Boolean
			Get
				Return m_enableCachedComposition
			End Get
			Set(ByVal value As Boolean)
				m_enableCachedComposition = value
				RaiseEvent PlaylistChanged(Me, Nothing)
			End Set
		End Property
		''' <summary>
		''' captions enabled
		''' </summary>
		<Description("Allow closed captions to show"), DefaultValue(True)> _
		Public Property EnableCaptions() As Boolean
			Get
				Return m_enableCaptions
			End Get
			Set(ByVal value As Boolean)
				m_enableCaptions = value
				RaiseEvent PlaylistChanged(Me, Nothing)
			End Set
		End Property
		''' <summary>
		''' offlining enabled
		''' </summary>
		<Description("Enable Player to be run offline"), DefaultValue(True)> _
		Public Property EnableOffline() As Boolean
			Get
				Return m_enableOffline
			End Get
			Set(ByVal value As Boolean)
				m_enableOffline = value
				RaiseEvent PlaylistChanged(Me, Nothing)
			End Set
		End Property
		''' <summary>
		''' popout enabled
		''' </summary>
		<Description("Enable Player popout"), DefaultValue(True)> _
		Public Property EnablePopOut() As Boolean
			Get
				Return m_enablePopOut
			End Get
			Set(ByVal value As Boolean)
				m_enablePopOut = value
				RaiseEvent PlaylistChanged(Me, Nothing)
			End Set
		End Property
		''' <summary>
		''' start in muted state
		''' </summary>
		<Description("Mute player on start")> _
		Public Property StartMuted() As Boolean
			Get
				Return m_startMuted
			End Get
			Set(ByVal value As Boolean)
				m_startMuted = value
				RaiseEvent PlaylistChanged(Me, Nothing)
			End Set
		End Property
		''' <summary>
		''' type of video stretch
		''' </summary>
		<Description("Stretch Mode")> _
		Public Property StretchMode() As Stretch
			Get
				Return m_stretchMode
			End Get
			Set(ByVal value As Stretch)
				m_stretchMode = value
				RaiseEvent PlaylistChanged(Me, Nothing)
			End Set
		End Property
		''' <summary>
		''' color of background
		''' </summary>
		Public Property Background() As Color
			Get
				Return m_background
			End Get
			Set(ByVal value As Color)
				m_background = value
				RaiseEvent PlaylistChanged(Me, Nothing)
			End Set
		End Property
		''' <summary>
		''' list of playlist items.
		''' </summary>
		<Description("Playlist")> _
		Public Property Items() As PlaylistCollection
			Get
				Return _Items
			End Get
			Set(ByVal value As PlaylistCollection)
				_Items = value
			End Set
		End Property
		''' <summary>
		''' init structure
		''' </summary>
		Private Sub Init()
			AutoLoad = True
			AutoPlay = True
			EnableCachedComposition = True
			EnableCaptions = True
			EnablePopOut = True
			EnableOffline = True
		End Sub
		''' <summary>
		''' construct a playlistitem, provided for scripting.
		''' </summary>
		''' <returns>new playlist item</returns>
		Public Function CreateNewPlaylistItem() As PlaylistItem
			Return New PlaylistItem(Items)
		End Function
		''' <summary>
		''' playlist constructor
		''' </summary>
		Public Sub New()
			StretchMode = Stretch.None
			_Items = New PlaylistCollection()
			AddHandler _Items.CollectionChanged, AddressOf Items_CollectionChanged
			Init()
		End Sub
		''' <summary>
		''' inform playlist changed if the items collection changed
		''' </summary>
		''' <param name="sender"></param>
		''' <param name="e"></param>
		Private Sub Items_CollectionChanged(ByVal sender As Object, ByVal e As System.Collections.Specialized.NotifyCollectionChangedEventArgs)
			RaiseEvent PlaylistChanged(Me, Nothing)
		End Sub
		''' <summary>
		''' create playlist from XML string
		''' </summary>
		''' <param name="playlistXml">XML string</param>
		''' <returns>playlist</returns>
		Public Shared Function Create(ByVal playlistXml As String) As Playlist
			Dim playlist As New Playlist()
			playlist.ParseXml(playlistXml)
			Return playlist
		End Function
		''' <summary>
		''' parse playlist from XML
		''' </summary>
		''' <param name="playlistXml"></param>
		Public Sub ParseXml(ByVal playlistXml As String)
			Dim enc As New UTF8Encoding()
			Using ms As New MemoryStream(enc.GetBytes(playlistXml))
				Dim xmlrs As New XmlReaderSettings()
				xmlrs.IgnoreComments = True
				xmlrs.IgnoreWhitespace = True
				Dim reader As XmlReader = XmlReader.Create(ms, xmlrs)
				Deserialize(reader)
			End Using
			RaiseEvent PlaylistChanged(Me, Nothing)
		End Sub
		#End Region

		#Region "Serialization"
		''' <summary>
		''' top level XML node for this class
		''' </summary>
		Friend Const xmlNode As String = "Playlist"
		''' <summary>
		''' deserialise this object
		''' </summary>
		''' <param name="reader">XmlReader to deserialize from</param>
		''' <returns>this</returns>
		Friend Sub Deserialize(ByVal reader As XmlReader)
			If Not reader.IsStartElement(Playlist.xmlNode) Then
				Throw New InvalidPlaylistException()
			End If

			Init()
			reader.Read()
			Do While Not(reader.Name = Playlist.xmlNode AndAlso reader.NodeType = XmlNodeType.EndElement)
				If reader.IsStartElement("AutoLoad") Then
					Me.AutoLoad = reader.ReadElementContentAsBoolean()
				ElseIf reader.IsStartElement("AutoPlay") Then
					Me.AutoPlay = reader.ReadElementContentAsBoolean()
				ElseIf reader.IsStartElement("DisplayTimeCode") Then
					Me.DisplayTimeCode = reader.ReadElementContentAsBoolean()
				ElseIf reader.IsStartElement("EnableCachedComposition") Then
					Me.EnableCachedComposition = reader.ReadElementContentAsBoolean()
				ElseIf reader.IsStartElement("EnableCaptions") Then
					Me.EnableCaptions = reader.ReadElementContentAsBoolean()
				ElseIf reader.IsStartElement("EnablePopOut") Then
					Me.EnablePopOut = reader.ReadElementContentAsBoolean()
				ElseIf reader.IsStartElement("EnableOffline") Then
					Me.EnableOffline = reader.ReadElementContentAsBoolean()
				ElseIf reader.IsStartElement("StartMuted") Then
					Me.StartMuted = reader.ReadElementContentAsBoolean()
				ElseIf reader.IsStartElement("StretchMode") Then
					Me.StretchMode = CType(System.Enum.Parse(GetType(Stretch), reader.ReadElementContentAsString(), False), Stretch)
				ElseIf reader.IsStartElement(PlaylistCollection.xmlNode) Then
					Me.Items.Clear()
					Me.Items.Deserialize(reader)
				ElseIf reader.IsStartElement() Then
					Throw New InvalidPlaylistException(reader.Name, Playlist.xmlNode)
				ElseIf Not reader.Read() Then
					Exit Do
				End If
			Loop
		End Sub
		''' <summary>
		''' serialize this object
		''' </summary>
		''' <param name="writer">XmlWriter</param>
		Friend Sub Serialize(ByVal writer As XmlWriter)
			writer.WriteStartElement(Playlist.xmlNode)
			writer.WriteElementString("AutoLoad", Me.AutoLoad.ToString().ToLower(CultureInfo.InvariantCulture))
			writer.WriteElementString("AutoPlay", Me.AutoPlay.ToString().ToLower(CultureInfo.InvariantCulture))
			writer.WriteElementString("DisplayTimeCode", Me.DisplayTimeCode.ToString().ToLower(CultureInfo.InvariantCulture))
			writer.WriteElementString("EnableCachedComposition", Me.EnableCachedComposition.ToString().ToLower(CultureInfo.InvariantCulture))
			writer.WriteElementString("EnableCaptions", Me.EnableCaptions.ToString().ToLower(CultureInfo.InvariantCulture))
			writer.WriteElementString("EnablePopOut", Me.EnablePopOut.ToString().ToLower(CultureInfo.InvariantCulture))
			writer.WriteElementString("EnableOffline", Me.EnableOffline.ToString().ToLower(CultureInfo.InvariantCulture))
			writer.WriteElementString("StartMuted", Me.StartMuted.ToString().ToLower(CultureInfo.InvariantCulture))
			writer.WriteElementString("StretchMode", Me.StretchMode.ToString())
			_Items.Serialize(writer)
			writer.WriteEndElement()
		End Sub
		#End Region

	End Class
End Namespace

